package com.zhouchj.elasticsearch.query;

import cn.hutool.core.text.CharSequenceUtil;
import com.zhouchj.elasticsearch.basic.EsQueryBuilderUtil;
import com.zhouchj.elasticsearch.basic.SFunction;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;

import java.util.Objects;

/**
 * ES分组查询构建
 *
 * @author zhouchj
 * @date 2023/8/24
 */
public class EsAggQuery<T, Column extends SFunction<T, ?>, Children extends EsBasicQuery<T, Column, Children>>
        extends EsBasicQuery<T, Column, Children> {

    protected EsAggQuery(Class<T> clazz,
                         IndexCoordinates index,
                         ElasticsearchRestTemplate elasticsearchRestTemplate) {
        super(clazz, index, elasticsearchRestTemplate);
    }


    /**
     * 添加分组
     * 默认bucketName为字段的驼峰
     *
     * @param func 字段
     * @return this
     */
    public Children agg(Column func) {
        String fieldName = this.convertToEsFieldName(clazz, func);
        String camelCase = CharSequenceUtil.toCamelCase(fieldName);
        EsQueryBuilderUtil.buildTermsAgg(builder, camelCase, fieldName);
        return typedThis;
    }

    /**
     * 添加分组
     *
     * @param bucketName 桶名
     * @param func       字段
     * @return this
     */
    public Children agg(String bucketName, Column func) {
        String fieldName = this.convertToEsFieldName(clazz, func);
        EsQueryBuilderUtil.buildTermsAgg(builder, bucketName, fieldName);
        return typedThis;
    }


    /**
     * 添加分组
     *
     * @param nestedFunc 嵌套字段
     * @param subFunc    子字段
     * @return this
     */
    public <C> Children agg(Column nestedFunc, SFunction<C, ?> subFunc) {
        String nestedFieldName = this.convertToEsFieldName(clazz, nestedFunc);
        String subFieldName = this.getSubEsFieldName(nestedFunc, subFunc);
        // 转换驼峰
        String camelCase = CharSequenceUtil.toCamelCase(subFieldName);
        EsQueryBuilderUtil.buildNestedAgg(builder, camelCase, nestedFieldName, subFieldName);
        return typedThis;
    }

    /**
     * 添加分组
     *
     * @param bucketName 桶名
     * @param nestedFunc 嵌套字段
     * @param subFunc    子字段
     * @return this
     */
    public <C> Children agg(String bucketName, Column nestedFunc, SFunction<C, ?> subFunc) {
        String nestedFieldName = this.convertToEsFieldName(clazz, nestedFunc);
        String subFieldName = this.getSubEsFieldName(nestedFunc, subFunc);
        EsQueryBuilderUtil.buildNestedAgg(builder, bucketName, nestedFieldName, subFieldName);
        return typedThis;
    }


    /**
     * 获取字段分组后前topSize条数据
     *
     * @param bucketName    外层分组桶名
     * @param topBucketName 内存top桶名
     * @param topSize       每个分组中的数据条数
     * @param topFunc       需要分组的字段
     * @return this
     */
    public Children topAgg(String bucketName,
                           String topBucketName,
                           int topSize,
                           Column topFunc) {
        return this.topAgg(bucketName, topBucketName, topSize, topFunc, null);
    }

    /**
     * 获取字段分组后前topSize条数据
     *
     * @param bucketName    外层分组桶名
     * @param topBucketName 内存top桶名
     * @param topSize       每个分组中的数据条数
     * @param topFunc       需要分组的字段
     * @param orderFunc     需要排序的字段
     * @return this
     */
    public Children topAgg(String bucketName,
                           String topBucketName,
                           int topSize,
                           Column topFunc,
                           Column orderFunc) {
        String fieldName = this.convertToEsFieldName(clazz, topFunc);
        String sortFieldName = null;
        if (Objects.nonNull(orderFunc)) {
            sortFieldName = this.convertToEsFieldName(clazz, orderFunc);
        }
        EsQueryBuilderUtil.buildTopAgg(builder, bucketName, topBucketName, topSize, fieldName, sortFieldName);
        return typedThis;
    }
}
